#include "mlgesture.h"
#include "gestureutils.h"
#include "control.h"
#include "skindetector.h"
#include "eventmanager.h"

using namespace mlgesture;

MLGesture::MLGesture(int video_id, int hands_num) throw(HandGestureException) {
	control_ = new Control(video_id, hands_num);
}

MLGesture::~MLGesture() {
	delete control_;
}

void MLGesture::startProcess() {
	control_->startThread();
}

void MLGesture::stopProcess() {
	control_->stopProcess();
}

bool MLGesture::getFrame(Mat &frame) const {
	vector<Rect> hands_rect;
	control_->getFrame(frame, &hands_rect);
	if (frame.empty())
		return false;
	for (size_t i=0; i<hands_rect.size(); i++) {
		rectangle(frame, hands_rect[i], Scalar(0, 255*(i%2), 255*((i+1)%2)), 2);
	}
	return true;
}

void MLGesture::getMask(Mat &mask) const {
	control_->getMask(mask);
}

Size MLGesture::getFrameSize() const {
	return control_->getFrameSize();
}

void MLGesture::setHandsNum(const int num) {
	control_->setHandsNum(num);
}

void MLGesture::adjustSkinFilter(const int lower_threshold, const int upper_threshold,
								   const int lower_value_threshold, const int upper_value_threshold) throw (HandGestureException) {
	control_->adjustSkinFilter(lower_threshold, upper_threshold, lower_value_threshold, upper_value_threshold);
}

void MLGesture::setAdaptiveAlgoritm(const bool adapt) {
	control_->setAdaptiveAlgoritm(adapt);
}

void MLGesture::adjustTrackingSensity(const double sensity) throw (HandGestureException) {
	control_->adjustTrackingSensity(sensity);
}

void MLGesture::releaseCamera() {
	control_->releaseCamera();
}

void MLGesture::getTrackShapeMask(vector<Mat>& shapes) const throw (HandGestureException) {
	const vector<Mat> &s = control_->getTrackShapeMask();
	shapes.clear();
	for (size_t i=0; i < s.size(); i++) {
		shapes.push_back(s[i].clone());
	}
}

void MLGesture::enableTrajectory(bool enable) {
	control_->enableTrajectory(enable);
}

const vector<Trajectory>& MLGesture::getTrajectory(vector<bool> &trajectory_status,
																  vector<bool> &trajectory_end) const throw (HandGestureException) {
	return control_->getTrajectory(trajectory_status, trajectory_end);
}

const vector<int>& MLGesture::getLastDirection() const throw (HandGestureException) {
	return control_->getLastDirection();
}

const vector<Point>& MLGesture::getLastPos() const throw (HandGestureException) {
	return control_->getLastPos();
}

void MLGesture::enableDynamicGesture(bool enable) throw (HandGestureException) {
	control_->enableDynamicGesture(enable);
}

void MLGesture::enableStaticGesture(bool enable) {
	control_->enableStaticGesture(enable);
}

void MLGesture::loadDynamicGestureModels(const vector<QString> &model_files, const QString &garbage_file) throw (HandGestureException) {
	control_->loadDynamicGestureModels(model_files, garbage_file);
}

void MLGesture::loadStaticGesturesModels(const QString &model_file, const QString &scale_factors_file,
										  const QString &labels_file) throw (HandGestureException) {
	control_->loadStaticGesturesModels(model_file, scale_factors_file, labels_file);
}

int MLGesture::getGlobalLowThreshold() {
	return SkinDetector::GSD_HUE_LT*2;
}

int MLGesture::getGlobalUpperThreshold() {
	return SkinDetector::GSD_HUE_UT*2;
}

int MLGesture::getGlobalValueLowThreshold() {
	return SkinDetector::GSD_INTENSITY_LT;
}

int MLGesture::getGlobalValueUpperThreshold() {
	return SkinDetector::GSD_INTENSITY_UT;
}

void MLGesture::addObserver(GestureObserver *observer) {
	EventManager::getInstance().addObserver(observer);
}

void MLGesture::removeObserver(GestureObserver *observer) {
	EventManager::getInstance().removeObserver(observer);
}
